package hku.cs.lunuo.run;

import hku.cs.instrument.Instrument;
import hku.cs.lunuo.LunuoLog;
import hku.cs.lunuo.LunuoPlugin;
import hku.cs.lunuo.util.LunuoLibHelper;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;

import soot.Scene;
import soot.options.Options;

public class ThreadRunner {
	private IJavaProject javaProject;

	public ThreadRunner(IJavaProject javaProject) {
		this.javaProject = javaProject;
	}

	public void run(final List<IJavaElement> jes) {

		// Display.getDefault().asyncExec(new Runnable() {
		// public void run() {
		IProject project = javaProject.getProject();

		List<String> filters;
		IResource resource = (IResource) project.getAdapter(IResource.class);
		try {
			String value = resource
					.getPersistentProperty(LunuoPlugin.FILTER_PROPERTY);
			if (value == null) {
				filters = Arrays.asList(new String[0]);
			} else
				filters = Arrays.asList(value.split(";"));
		} catch (CoreException e) {
			LunuoLog.logError(e);
			filters = Arrays.asList(new String[0]);
		}

		try {
			List<String> sourceDirs = new ArrayList<String>();
			IClasspathEntry xx[] = javaProject.getRawClasspath();

			for (int i = 0; i < xx.length; i++)
				if (xx[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
					sourceDirs.add(xx[i].getPath().toString());
				}

			List<String> runClasses = new ArrayList<String>();

			for (IJavaElement je : jes) {
				String stre = je.getPath().toString();
				for (String osd : sourceDirs) {
					if (stre.startsWith(osd)) {
						stre = stre.substring(osd.length() + 1, stre.length());
						break;
					}
				}
				stre = stre.replace('/', '.');
				stre = stre.substring(0, stre.lastIndexOf('.'));

				if (stre.lastIndexOf('.') != -1) {
					if (!filters.contains(stre.substring(0, stre
							.lastIndexOf('.')))) {
						runClasses.add(stre);
					}
				} else {
					if (!filters.contains("(default package)")) {
						runClasses.add(stre);
					}
				}
			}
			if (runClasses.size() > 0) {
				soot.G.reset();
				String classpath = LunuoLibHelper
						.urlsToString(getSootClassPath());
				Scene.v().setSootClassPath(classpath);
				String output = ".";
				output = LunuoPlugin.METADIR.append(
						javaProject.getOutputLocation()).toOSString();
				Options.v().set_output_dir(output);				
				Instrument.main(runClasses.toArray(new String[0]));			
			}
		} catch (JavaModelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// }
		// });

	}

	private URL[] getSootClassPath() {
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IClasspathEntry[] cp;
		try {
			cp = javaProject.getResolvedClasspath(true);
			Set<URL> urls = new HashSet<URL>();

			for (IClasspathEntry entry : cp) {
				if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
					URI uri = new URI(workspace.getRoot().getFile(
							entry.getPath()).getLocationURI().toString()
							+ "/");
					urls.add(uri.toURL());
				} else {
					File file = entry.getPath().toFile();
					URL url = file.toURI().toURL();
					urls.add(url);
				}
			}
			IClasspathEntry[] lcp = LunuoLibHelper
					.getClientSideWithLibEntries();
			for (IClasspathEntry entry : lcp) {
				File file = entry.getPath().toFile();
				URL url = file.toURI().toURL();
				urls.add(url);
			}

			URL[] array = new URL[urls.size() + 1];
			String uriString = workspace.getRoot().getFile(
					javaProject.getOutputLocation()).getLocationURI()
					.toString()
					+ "/";
			array[0] = new URI(uriString).toURL();
			Iterator<URL> i = urls.iterator();
			int j = 1;
			while (i.hasNext()) {
				array[j] = i.next();
				j++;
			}

			return array;

		} catch (JavaModelException e) {
			e.printStackTrace();
			return new URL[0];
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return new URL[0];
		} catch (URISyntaxException e) {
			e.printStackTrace();
			return new URL[0];
		}
	}
}
